package cn.mehoyo.certificateGeneration;

import org.shredzone.acme4j.*;
import org.shredzone.acme4j.challenge.Dns01Challenge;
import org.shredzone.acme4j.util.CSRBuilder;
import org.shredzone.acme4j.util.KeyPairUtils;
import java.io.FileWriter;
import java.security.KeyPair;
import java.security.Security;
import java.security.cert.X509Certificate;
import java.util.Scanner;
import java.util.concurrent.TimeUnit;

public class LocalGeneration {

    public static void main(String[] args) throws Exception {
        Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());

        Scanner scanner = new Scanner(System.in);
        System.out.print("请输入泛域名（如 *.example.com）: ");
        String domain = scanner.nextLine().trim();

        if (!domain.startsWith("*.")) {
            System.out.println("必须输入泛域名，以 '*.' 开头！");
            return;
        }

        // 1. 创建账户密钥对
        KeyPair accountKey = KeyPairUtils.createKeyPair(2048);
        Session session = new Session("acme://letsencrypt.org");

        // 2. 注册账户
        Account account = new AccountBuilder().useKeyPair(accountKey).agreeToTermsOfService().create(session);

        // 3. 创建域名密钥对
        KeyPair domainKey = KeyPairUtils.createKeyPair(2048);

        // 4. 创建订单
        Order order = account.newOrder().domain(domain).create();

        // 5. 处理 DNS 验证
        for (Authorization auth : order.getAuthorizations()) {
            Dns01Challenge challenge = (Dns01Challenge) auth.findChallenge(Dns01Challenge.TYPE).get();
            if (challenge == null) {
                throw new IllegalStateException("未找到 DNS-01 验证类型");
            }

            String digest = challenge.getDigest();
            String recordName = "_acme-challenge." + auth.getIdentifier().getDomain();

            System.out.println("请将 DNS TXT 添加如下：");
            System.out.println("  记录名: " + recordName);
            System.out.println("  记录值: " + digest);

            System.out.println("DNS 添加后，按回车继续...");
            scanner.nextLine();

            challenge.trigger();
            int retries = 10;
            while (challenge.getStatus() != Status.VALID && retries-- > 0) {
                TimeUnit.SECONDS.sleep(5);
                challenge.update();
            }

            if (challenge.getStatus() != Status.VALID) {
                throw new RuntimeException("DNS 验证失败！");
            }
        }
        // 6. 生成 CSR
        CSRBuilder csrb = new CSRBuilder();
        csrb.addDomain(domain);
        csrb.sign(domainKey);

        // 7. 提交 CSR
        order.execute(csrb.getEncoded());
        while (order.getStatus() != Status.VALID) {
            TimeUnit.SECONDS.sleep(5);
            order.update();
        }

        // 8. 保存证书
// 8. 获取并保存证书
        Certificate cert = order.getCertificate();
        if (cert == null) {
            System.out.println("未能获取到证书，请稍后重试！");
            return;
        }

// 保存 PEM 文件
        try (FileWriter fw = new FileWriter("cert.pem")) {
            for (X509Certificate c : cert.getCertificateChain()) {
                fw.write("-----BEGIN CERTIFICATE-----\n");
                fw.write(java.util.Base64.getMimeEncoder(64, new byte[]{'\n'}).encodeToString(c.getEncoded()));
                fw.write("\n-----END CERTIFICATE-----\n\n");
            }
        }
        System.out.println("证书保存至cert.pem");
// 保存私钥
        try (FileWriter fw = new FileWriter("cert.key")) {
            KeyPairUtils.writeKeyPair(domainKey, fw);
        }
        System.out.println("私钥保存至 " + "cert.key");
    }
}
